package com.hdl.client.utils;

import com.hdl.RpcRequest;
import com.hdl.client.consumer.ServiceDiscover;
import com.hdl.client.handler.NettyClientHandler;
import com.hdl.client.handler.NettyClientHandlerSingleton;

import java.lang.reflect.Proxy;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 类名 ConsumerProxy
 * 描述 TODO
 *
 * @author hedonglin
 * @version 1.0
 * @date 2020/6/17 17:31
 */
public class ConsumerProxy {
    private static ExecutorService executor =
            Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    /*** 创建一个代理对象 */
    public static Object createProxy(final Class<?> serviceClass) {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{serviceClass}, (proxy, method, args) -> {
            NettyClientHandler client = null;
            if (ServiceDiscover.clientHandlers.size() == 0) {
                System.out.println("没有可调用的服务器");
                return "服务器还未准备好，请稍后重试!";
            } else {
                System.out.println("==============================================================");
                for (NettyClientHandler clientHandler : ServiceDiscover.clientHandlers) {
                    System.out.println("=========>>>>>>>>服务器:" + clientHandler.getConnectString() +  "，最近响应时间：" + clientHandler.getResponseTime() + " ms");
                }
                System.out.println("==============================================================");
                //                // 随机
//                int index = new Random().nextInt(ServiceDiscover.clientHandlers.size());
                // 过滤出响应时间最短的服务器(且时间大于0), 按响应时间排序去第一个即可，如果响应时间相同，取第一个也相当于随机， 为0的会优先调用
                client = ServiceDiscover.clientHandlers.stream().min(Comparator.comparingLong(NettyClientHandler::getResponseTime)).get();
//                client = ServiceDiscover.clientHandlers.get(index);
            }
            final RpcRequest rpcRequest = new RpcRequest();
            rpcRequest.setClassName(serviceClass.getName());
            rpcRequest.setClazz(serviceClass);
            // 设置参数
            rpcRequest.setParameters(args);
            rpcRequest.setMethodName(method.getName());
            rpcRequest.setRequestId(UUID.randomUUID().toString().replaceAll("-", ""));

            // 设置参数类型
            if (args.length > 0) {
                Class<?>[] paramsTypes = new Class[args.length];
                for (int i = 0; i < args.length; i++) {
                    Class<?> aClass = args[i].getClass();
                    paramsTypes[i] = aClass;
                }
                rpcRequest.setParameterTypes(paramsTypes);
            }
            client.setPara(rpcRequest);

            // 如果5s还没获取到结果，进行服务降级，直接返回提示数据
            try {
                return executor.submit(client).get(5000, TimeUnit.MILLISECONDS);
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }catch (TimeoutException e){
                e.printStackTrace();
                return "调用服务器超时，请稍后重试!";
            }
            return "服务器异常，请稍后重试!";
        });
    }
}
